import decimal
import os
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont, ImageColor

from tool.tools import getEnvConfig
IMAGE_DIR = r'E:\project\nobad\resource\image'

def draw_rounded_gradient_deep_bar(
    score,
    width=400,
    height=40,
    radius=20,
    start_color="#7B61FF",  # Purple
    mid_color="#FF9BDB",    # Pink
    end_color="#FF0000",    # Red
    bg_color="#e7d9f3"
):
    score = max(score, 10)
    img = Image.new("RGBA", (width, height), color=(0, 0, 0, 0))
    draw = ImageDraw.Draw(img)
    bg_rect = (0, 0, width-2, height)
    draw.rounded_rectangle(bg_rect, radius=radius, fill=bg_color)
    fill_width = int(score / 100 * width)
    if fill_width <= 0:
        return img
    fill_width = min(fill_width, width)
    fill_rect = (radius, 0, fill_width-12, height)
    max_fill_width = width
    for x in range(fill_rect[0], fill_rect[2]):
        ratio = (x - fill_rect[0]) / max_fill_width
        ratio = min(ratio, 1.0)
        if ratio <= 0.5:
            local_ratio = ratio * 2
            base_color = ImageColor.getrgb(start_color)
            target_color = ImageColor.getrgb(mid_color)
        else:
            local_ratio = (ratio - 0.5) * 2
            base_color = ImageColor.getrgb(mid_color)
            target_color = ImageColor.getrgb(end_color)
        r = int(base_color[0] + local_ratio * (target_color[0] - base_color[0]))
        g = int(base_color[1] + local_ratio * (target_color[1] - base_color[1]))
        b = int(base_color[2] + local_ratio * (target_color[2] - base_color[2]))
        tail_color = (r, g, b)
        draw.rectangle((x, fill_rect[1], x + 1, fill_rect[3]), fill=(r, g, b))
    head_radius = min(radius, fill_width)
    if head_radius > 0:
        draw.pieslice(
            (fill_rect[0] - head_radius, 0,
             fill_rect[0] + head_radius, 2 * head_radius),
            start=90, end=270, fill=start_color
        )
    tail_radius = min(radius, fill_width)
    if tail_radius > 0:
        draw.pieslice(
            (fill_rect[2] - tail_radius, height-2 * tail_radius,
             fill_rect[2] + tail_radius, height),
            start=270, end=90, fill=tail_color
        )
    return img


def generate_risk_advice_image(json_data, output_file_url):
    """生成宽度500px的长图（左对齐+背景留白300px+裁剪拼接）"""
    # 配置路径
    pingfangSc_path = r"E:\project\nobad\resource\font\PingFangSc.ttc"
    pingfang_path = r"E:\project\nobad\resource\font\PingFang.ttc"

    alimama_path = r"E:\project\nobad\resource\font\AlimamaShuHeiTi-Bold.ttf"
    icon1_path = r"E:\project\nobad\resource\sign\action_1.png"
    icon2_path = r"E:\project\nobad\resource\sign\action_2.png"
    bg_path = r"E:\project\nobad\resource\sign\backdeep.png"  # 背景图路径
    bucket_name = getEnvConfig('TENCENT_COS_BUCKET', 'crashcheck-1256118830')
    file_name = output_file_url.split("img/")[1]
    local_img_path = f"{IMAGE_DIR}/{file_name}"

    # ---------------------- 1. 加载背景图（保留原始大小） ----------------------
    decimal.getcontext().prec = 20
    bg_img = Image.open(bg_path).convert("RGBA")
    bg_width, bg_height = bg_img.size  # 948*6125
    target_width = 500
    bg_scale_ratio = decimal.Decimal(target_width) / decimal.Decimal(bg_width)  # 缩放比例

    # ---------------------- 2. 创建临时画布绘制内容 ----------------------
    temp_height = 3000  # 临时高度用于绘制内容
    temp_canvas = Image.new("RGBA", (target_width, temp_height), (255, 255, 255, 0))
    draw = ImageDraw.Draw(temp_canvas)

    # ---------------------- 3. 配置字体 ----------------------
    try:
        font_summary = ImageFont.truetype(pingfangSc_path, 20)
        font_summary_advise_text = ImageFont.truetype(pingfang_path, 20)
        font_fengxian = ImageFont.truetype(pingfangSc_path, 22)
        font_socre_fengxian = ImageFont.truetype(pingfang_path, 18)
        font_17_alimama = ImageFont.truetype(alimama_path, 26)
    except OSError as e:
        raise Exception(f"字体加载失败：{e}")

    # ---------------------- 4. 绘制“风险评分与行动建议”（左对齐+层叠） ----------------------
    icon1 = Image.open(icon1_path).convert("RGBA")
    title1 = "风险评分与行动建议"
    title1_bbox = draw.textbbox((0, 0), title1, font=font_17_alimama)
    title1_width = title1_bbox[2]
    title1_height = title1_bbox[3]

    # 图标层叠：图标作为背景，文字左对齐覆盖（左间距30px）
    icon1_width = title1_width + 85  # 图标宽度
    icon1_height = title1_height + 30 #底图高度高度
    icon1 = icon1.resize((icon1_width, icon1_height), Image.Resampling.LANCZOS)
    # 位置：左对齐30px，背景留白300px后
    content_start_y = 132  # 背景顶部留白300px
    icon1_x = 0   # 左侧【底部图片】距离上方高度
    icon1_y = content_start_y
    title1_x = icon1_x + (icon1_width - title1_width) // 2  +12 # 图标右侧间距10px  文字距离左侧
    title1_y = icon1_y + (icon1_height - title1_height) // 2
    # 先画图标（背景），再画文字（层叠覆盖）
    temp_canvas.paste(icon1, (icon1_x, icon1_y), mask=icon1)
    draw.text((title1_x, title1_y), title1, font=font_17_alimama, fill=(255, 255, 255, 255))

    # ---------------------- 5. 绘制summary段落风险评分与行动建议 ----------------------
    summary = json_data["summary"]
    summary_x = 42
    summary_y = icon1_y + icon1_height + 30
    max_width_summary = target_width - 90
    chars = list(summary)
    current_line = ""
    lines = []
    for char in chars:
        test_line = current_line + char
        if draw.textlength(test_line, font=font_summary) <= max_width_summary:
            current_line = test_line
        else:
            lines.append(current_line)
            current_line = char
    if current_line:
        lines.append(current_line)
    for line in lines:
        draw.text((summary_x, summary_y), line, font=font_summary, fill=(51, 51, 51, 255))
        summary_y += font_summary.getbbox("测")[3] + 8

    # ---------------------- 6. 绘制flags进度条（风险等级靠右） ----------------------
    flags = json_data["flags"]
    progress_y = summary_y + 24 # 进度条区域距离上不距离
    for flag_name, score in flags.items():
        # 风险等级判断
        if score < 20:
            risk_level = "低风险"
        elif score < 40:
            risk_level = "中低风险"
        elif score < 60:
            risk_level = "中风险"
        else:
            risk_level = "高风险"

        # 标题左侧，风险等级右侧显示
        flag_title = f"{flag_name}：{score} %"
        # 计算风险等级宽度，靠右对齐
        risk_level_bbox = draw.textbbox((0, 0), risk_level, font=font_fengxian)
        risk_level_width = risk_level_bbox[2]
        risk_level_x = target_width - 40 - risk_level_width  # 右侧边距30px

        # 绘制左侧标题和右侧风险等级
        draw.text((summary_x, progress_y), flag_title, font=font_fengxian, fill=(61, 61, 61, 255))
        draw.text((risk_level_x, progress_y), risk_level, font=font_socre_fengxian, fill=(61, 61, 61, 200))

        # 生成进度条
        progress_bar = draw_rounded_gradient_deep_bar(score, width=410, height=20, radius=10)

        bar_x = summary_x
        bar_y = progress_y + 46 # 文字距离进度条的位置
        temp_canvas.paste(progress_bar, (bar_x, bar_y), mask=progress_bar)
        progress_y = bar_y + 46

    # ---------------------- 7. 绘制风险与建议 ----------------------
    # 最隐蔽风险

    hidden_risk_title = " · 最隐蔽风险："
    hidden_risk_content = json_data["danger"]
    draw.text((summary_x, progress_y), hidden_risk_title, font=font_summary, fill=(51, 51, 51, 255))
    title_bbox = draw.textbbox((0, 0), hidden_risk_title, font=font_summary)
    title_width = title_bbox[2]

    # 为最隐蔽风险内容添加自动换行
    hidden_risk_lines = []
    current_line = ""
    for char in hidden_risk_content:
        test_line = current_line + char
        if draw.textlength(test_line, font=font_summary_advise_text) <= (max_width_summary - title_width):
            current_line = test_line
        else:
            hidden_risk_lines.append(current_line)
            current_line = char
    if current_line:
        hidden_risk_lines.append(current_line)
    # 绘制多行文本
    line_height = font_summary_advise_text.getbbox("测")[3] + 8
    for i, line in enumerate(hidden_risk_lines):
        draw.text((summary_x + title_width, progress_y + i * line_height), line, font=font_socre_fengxian, fill=(51, 51, 51, 200))
    progress_y += len(hidden_risk_lines) * line_height

    # 行动建议
    advise_title = " · 行动建议："
    advise_content = json_data["advise"]
    draw.text((summary_x, progress_y), advise_title, font=font_summary, fill=(51, 51, 51, 255))
    title_bbox = draw.textbbox((0, 0), advise_title, font=font_summary)
    title_width = title_bbox[2]

    # 为行动建议内容添加自动换行
    advise_lines = []
    current_line = ""
    for char in advise_content:
        test_line = current_line + char
        if draw.textlength(test_line, font=font_summary_advise_text) <= (max_width_summary - title_width):
            current_line = test_line
        else:
            advise_lines.append(current_line)
            current_line = char
    if current_line:
        advise_lines.append(current_line)

    # 绘制多行文本
    line_height = font_summary_advise_text.getbbox("测")[3] + 8
    for i, line in enumerate(advise_lines):
        draw.text((summary_x + title_width, progress_y + i * line_height), line, font=font_summary_advise_text, fill=(51, 51, 51, 200))
    progress_y += len(advise_lines) * line_height

    # 行动建议总结
    advise_summary_title = "结论："
    advise_summary_content = json_data["advise_summary"]
    draw.text((summary_x, progress_y), advise_summary_title, font=font_summary, fill=(51, 51, 51, 255))
    title_bbox = draw.textbbox((0, 0), advise_summary_title, font=font_summary)
    title_width = title_bbox[2]

    # 为行动建议总结内容添加自动换行
    advise_summary_lines = []
    current_line = ""
    for char in advise_summary_content:
        test_line = current_line + char
        if draw.textlength(test_line, font=font_summary_advise_text) <= (max_width_summary - title_width):
            current_line = test_line
        else:
            advise_summary_lines.append(current_line)
            current_line = char
    if current_line:
        advise_summary_lines.append(current_line)

    # 绘制多行文本
    line_height = font_summary_advise_text.getbbox("测")[3] + 8
    for i, line in enumerate(advise_summary_lines):
        draw.text((summary_x + title_width, progress_y + i * line_height), line, font=font_summary_advise_text, fill=(51, 51, 51, 200))
    progress_y = progress_y + len(advise_summary_lines) * line_height

    # ---------------------- 8. 绘制“详细解读”（左对齐+层叠） ----------------------
    icon2 = Image.open(icon2_path).convert("RGBA")
    title2 = "详细解读"
    title2_bbox = draw.textbbox((0, 0), title2, font=font_17_alimama)
    title2_width = title2_bbox[2]
    title2_height = title2_bbox[3]

    # 图标层叠设置
    icon2_width = title2_width + 85  # 图标长度
    icon2_height = title2_height + 30  # 图标高度

    icon2 = icon2.resize((icon2_width, icon2_height), Image.Resampling.LANCZOS)
    # 位置：左对齐30px
    icon2_x = 0
    icon2_y = progress_y + 30 # 详细解读距离上一段距离
    title2_x = icon2_x + (icon2_width - title2_width)//2 +12  # 详细解读文字左距离
    title2_y = icon2_y + (icon2_height - title2_height) // 2
    # 层叠绘制
    temp_canvas.paste(icon2, (icon2_x, icon2_y), mask=icon2)
    draw.text((title2_x, title2_y), title2, font=font_17_alimama, fill=(255, 255, 255, 255))

    # ---------------------- 9. 绘制detail内容 ----------------------
    detail = json_data["detail"]
    detail_y = icon2_y + icon2_height + 20
    detail_index = 1
    for key, value in detail.items():
        key_with_index = f"{detail_index}. {key}"
        draw.text((summary_x, detail_y), key_with_index, font=font_summary, fill=(51, 51, 51, 255))
        detail_y += font_summary.getbbox("测")[3] + 8

        # 修改此处：为detail内容添加与前面相同的行宽限制
        value_chars = list(value)
        value_current_line = ""
        value_lines = []
        # 使用(max_width_summary - 20)来为缩进留出空间
        for char in value_chars:
            test_line = value_current_line + char
            if draw.textlength(test_line, font=font_summary_advise_text) <= (max_width_summary - 20):
                value_current_line = test_line
            else:
                value_lines.append(value_current_line)
                value_current_line = char
        if value_current_line:
            value_lines.append(value_current_line)

        for line in value_lines:
            draw.text((summary_x + 20, detail_y), line, font=font_summary_advise_text, fill=(51, 51, 51, 200))
            detail_y += font_summary_advise_text.getbbox("测")[3] + 5
        detail_index += 1
        detail_y += 15
    # ---------------------- 10. 裁剪内容画布到实际高度 ----------------------
    content_total_height = detail_y + 20
    temp_canvas_cropped = temp_canvas.crop((0, 0, target_width, content_total_height))

    # ---------------------- 11. 处理背景图：保留顶部300px、底部300px，中间裁剪拼接 ----------------------
    # 缩放背景图的顶部300px和底部300px（按比例）
    bg_top_height_original = 50
    bg_bottom_height_original = 50
    bg_top_height_scaled = int(bg_top_height_original * bg_scale_ratio)
    bg_bottom_height_scaled = int(bg_bottom_height_original * bg_scale_ratio)

    # 裁剪背景图的顶部和底部（缩放后）
    bg_img_scaled = bg_img.resize((target_width, int(bg_height * bg_scale_ratio)), Image.Resampling.LANCZOS)
    bg_top = bg_img_scaled.crop((0, 0, target_width, bg_top_height_scaled))
    bg_bottom = bg_img_scaled.crop(
        (0, bg_img_scaled.height - bg_bottom_height_scaled, target_width, bg_img_scaled.height))

    # 计算中间需要的背景高度（内容高度 - 顶部高度）
    bg_mid_needed_height = content_total_height - bg_top_height_scaled
    if bg_mid_needed_height < 0:
        bg_mid_needed_height = 0

    # 裁剪背景图的中间部分（从顶部300px后取需要的高度）
    bg_mid_start_y = bg_top_height_scaled
    bg_mid_end_y = bg_mid_start_y + bg_mid_needed_height
    if bg_mid_end_y > bg_img_scaled.height - bg_bottom_height_scaled:
        bg_mid_end_y = bg_img_scaled.height - bg_bottom_height_scaled
    bg_mid = bg_img_scaled.crop((0, bg_mid_start_y, target_width, bg_mid_end_y))

    # ---------------------- 12. 拼接背景图：顶部 + 中间 + 底部 ----------------------
    final_bg_height = bg_top_height_scaled + bg_mid_needed_height + bg_bottom_height_scaled
    final_bg = Image.new("RGBA", (target_width, final_bg_height), (255, 255, 255, 0))
    # 粘贴顶部
    final_bg.paste(bg_top, (0, 0))
    # 粘贴中间
    final_bg.paste(bg_mid, (0, bg_top_height_scaled))
    # 粘贴底部
    final_bg.paste(bg_bottom, (0, bg_top_height_scaled + bg_mid_needed_height))

    # ---------------------- 13. 将内容叠加到背景图（内容从顶部px开始） ----------------------
    final_img = Image.new("RGBA", (target_width, final_bg_height), (255, 255, 255, 0))
    final_img.paste(final_bg, (0, 0))
    # 内容叠加位置：背景顶部px（缩放后）对应内容的0位置
    final_img.paste(temp_canvas_cropped, (0, 0), mask=temp_canvas_cropped)

    # ---------------------- 14. 保存图片（无损PNG） ----------------------
    os.makedirs(IMAGE_DIR, exist_ok=True)
    final_img.save(local_img_path, format="PNG")


# 调用示例
json_data = {
    'advise': '保持互动观察，避免过早投入情感，优先确认对方真实动机撒旦发大师傅撒旦发射点发撒旦发射点发',
    'advise_summary': '警惕视觉符号表演性，重点验证互动中的真实意图撒范德萨打发士大夫士大夫大师傅撒旦',
    'danger': '幼态化头像与腮红特效伪装‘易掌控感’，为后续情感索取铺垫撒旦范德萨打发',
    'detail': {
        '内容表演': '10公里运动分享存在‘运动人设’表演倾向，未直接展示真实运动记录，仅用文字暗示能力，符合‘表演型人格价值预支范式’',
        '视觉符号': '头像为戴帽猫幼态化编码（符合犯罪心理学‘退行性防御机制’），高频使用腮红特效（纯欲风滤镜），根据3.5亿用户行为库，此类视觉符号表演倾向账号索取倾向高4.2倍',
        '身份透明': '账号ID与签名无伪装痕迹，根据32000例实锤案例，无多账号运营特征，但视觉符号策略性强导致风险提升'
    },
    'flags': {'价值预支': 10, '情感操控': 45, '表演性视觉': 75, '责任规避': 100},
    'summary': '该账号通过戴帽猫头像（幼态化）和腮红特效构建表演型人格，动态内容虽日常但视觉符号存在低真诚度风险，无明显物质索取倾向但需警惕互动中的情感操控，综合风险评分42分（中等风险）。'
}
generate_risk_advice_image(json_data, "img/risk_advice_001.png")